import 'dart:convert';
import 'dart:typed_data';

import 'package:business_plugin/business/config_business/config_business.dart';
import 'package:crypto/crypto.dart';

import 'package:get/get.dart';
import 'package:pointycastle/api.dart';

import 'firebase_helper.dart';

/// firebase remoteConfig解密
class FirebaseRemoteConfigService extends GetxService {
  static FirebaseRemoteConfigService get to => Get.find();

  // app 包名 解密用的
  late String packageName;

  @override
  void onInit() {
    super.onInit();
    packageName = ConfigBusiness.config.iosBundleId;

    // PackageInfo.fromPlatform().then((value) {
    //   packageName = iosBundleId;
    // });
  }

  String getString(String key, {String defaultValue = ""}) {
    final all = FirebaseHelper.remoteConfig.getAll();

    final remoteKey = _encryptByPName(key);
    final remoteValue = FirebaseHelper.remoteConfig.getString(remoteKey);
    if (remoteValue.isEmpty) {
      return defaultValue;
    }
    return _decryptByPName(remoteValue);
  }

  bool getBoolean(String key, {bool defaultValue = false}) {
    return bool.tryParse(getString(key)) ?? defaultValue;
  }

  double getDouble(String key, {double defaultValue = 0.0}) {
    return double.tryParse(getString(key)) ?? defaultValue;
  }

  int getInt(String key, {int defaultValue = 0}) {
    return int.tryParse(getString(key)) ?? defaultValue;
  }

  Map getMap(String key, {defaultValue = '{}'}) {
    return jsonDecode(getString(key, defaultValue: defaultValue));
  }

  List getList(String key, {defaultValue = '[]'}) {
    String value = getString(key, defaultValue: defaultValue);
    return jsonDecode(value.isEmpty ? defaultValue : value);
  }

  ///  ================
  ///  以下是在线参数加解密
  ///  ================
  String _decryptByPName(String encrypted) {
    if (encrypted.isEmpty) {
      return encrypted;
    }
    if (encrypted.startsWith("ccb")) {
      encrypted = encrypted.substring(3);
    }
    return _decrypt(_getKey(), encrypted);
  }

  String _encryptByPName(String content) {
    return "ccb${_encrypt(_getKey(), content)}";
  }

  String _getKey() {
    return md5.convert(packageName.codeUnits).toString().toUpperCase();
  }

  String _encrypt(String key, String content) {
    final Uint8List inputData = utf8.encode(content);
    final md5Digest = md5.convert(utf8.encode(key));

    final keyParameter = KeyParameter(Uint8List.fromList(md5Digest.bytes));
    final keyParameter2 = PaddedBlockCipherParameters(keyParameter, keyParameter);

    final PaddedBlockCipher cipher = PaddedBlockCipher('AES/ECB/PKCS7');
    cipher.init(true, keyParameter2); // true for e

    final Uint8List cipherText = cipher.process(inputData);
    final str = _parseByte2HexStr(cipherText);
    return str;
  }

  String _decrypt(String key, String content) {
    // Convert the hexadecimal string to bytes
    final Uint8List inputData = _hexToBytes(content);
    final md5Digest = md5.convert(utf8.encode(key));

    final keyParameter = KeyParameter(Uint8List.fromList(md5Digest.bytes));
    final keyParameter2 = PaddedBlockCipherParameters(keyParameter, keyParameter);
    final PaddedBlockCipher cipher = PaddedBlockCipher('AES/ECB/PKCS7');
    cipher.init(false, keyParameter2); // false for decryption

    // Decrypt the data
    final Uint8List decryptedData = cipher.process(inputData);
    // Convert the decrypted bytes back to a UTF-8 string
    final str = utf8.decode(decryptedData);
    return str;
  }

  // Helper function to convert a hexadecimal string to bytes
  Uint8List _hexToBytes(String hex) {
    final buffer = Uint8List(hex.length ~/ 2);
    for (int i = 0; i < hex.length; i += 2) {
      final byteString = hex.substring(i, i + 2);
      final byteValue = int.parse(byteString, radix: 16);
      buffer[i ~/ 2] = byteValue;
    }
    return buffer;
  }

  // Helper function to convert bytes to a hexadecimal string
  String _parseByte2HexStr(Uint8List byteData) {
    final StringBuffer buffer = StringBuffer();
    for (final byte in byteData) {
      buffer.write(byte.toRadixString(16).padLeft(2, '0'));
    }
    return buffer.toString();
  }
}
